#include "blockQueue.hpp"                                                           
#include "Task.hpp"    
#include <pthread.h>
#include <unistd.h> 
      
// 加法函数，用于生产者进程产生任务
int myAdd(int x, int y)    
{    
    return x + y;    
}    

// 消费者进程
void *consumer(void* args)    
{  
  // 将获得的agrs 参数 强制转化为BlockQueue<Task>* 类型 并赋值给变量bqueue
  BlockQueue<Task>* bqueue = (BlockQueue<Task>*)args;
  
  while(true)
  {
    // 获取任务
    Task t;
    bqueue->pop(&t); // 执行任务 + 销毁
    // 打印任务信息，因为我们使用的仅仅是一个加法函数，所以直接打印"+"
    cout << pthread_self() << " consumer: " << t._x << " + " << t._y << " = " << t() << endl;
  }

  return nullptr;
}

// 生产者进程
void* productor(void* args)
{
  BlockQueue<Task>* bqueue = (BlockQueue<Task>*)args;

  while(true)
  {
    // 制造任务
    // 生产者将任务传到缓冲区，消费者再将其消耗
    // 任务不一定有生产者制造，也可能通过外部获得

    // 随机产生x, y两个参数，执行Task
    int x = rand() % 10 + 1;
    usleep(rand() % 1000);  
    int y = rand() % 5 + 1;

    Task t(x, y, myAdd);
    // 发送任务
    bqueue->push(t);
    // 输出消息
    cout << pthread_self() << " productor: " << t._x << " + " << t._y << " = ?" << endl;
    sleep(1);
  }
  return nullptr;
}

int main()
{
  // getpid()：获取当前进程的进程ID（PID），用于区分不同的进程。
  // 0x11451 用于增加种子的随机性
  srand((uint64_t)time(nullptr) ^ getpid() ^ 0x11451);

  BlockQueue<Task>* bqueue = new BlockQueue<Task>();

  pthread_t con[2], pro[2]; // 声明两个消费者 / 生产者，增加并行性
  // 可以将 &con[1] 换为 con+1
  pthread_create(&con[0], nullptr, consumer, bqueue);
  pthread_create(&con[1], nullptr, consumer, bqueue);
  pthread_create(&pro[0], nullptr, productor, bqueue);
  pthread_create(&pro[1], nullptr, productor, bqueue);

  // 执行完毕，等待进程销毁
  pthread_join(con[0], nullptr);
  pthread_join(con[1], nullptr);
  pthread_join(pro[0], nullptr);
  pthread_join(pro[1], nullptr);

  delete bqueue; // 销毁队列
  
  return 0;
}